package br.usfacar.acumaaf.smc.webservice;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import br.ufscar.acumaaf.smc.dao.UsuarioDAO;
import br.ufscar.acumaaf.smc.model.Usuario;

import android.content.Context;
import android.os.Looper;
import android.util.Log;

public class RestClientUsuario{
	
	//teste na máquina remota
	public final static String ENDERECO_WEBSERVICE_SINCRONIZA_USUARIO = "http://192.168.1.103:8080/ACUMAAF-SIAF/jaxrs/sincronizaUsuario";
	//teste no localhost
	//public final static String ENDERECO_WEBSERVICE_SINCRONIZA_USUARIO = "http://10.0.2.2:8080/ACUMAAF-SIAF/jaxrs/sincronizaUsuario";
	
	private static List<Usuario> listaUsuario;
	
	public static String convertStreamToString(InputStream is){
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		//Log.i("smc","RestClient:BufferedReader reader = " + reader);
		StringBuilder sb = new StringBuilder();
		//Log.i("smc","RestClient:StringBuilder sb = " + sb + "|Antes do while");
		String line = null;
		try{
			line = reader.readLine();
			sb.append(line);
			//while((line = reader.readLine()) != null){
			//	sb.append(line + "\n");
			//	Log.i("smc","RestClient:sb = " + sb + "| Durante o while");
			//}
		}catch (Exception e){
			e.printStackTrace();
		}finally{
			try{
				is.close();
			}catch (IOException e){
				e.printStackTrace();
			}
		}
		return sb.toString();
	}	
	
	/**
	 * 
	 * Métodos getDadosTabelaUsuarioSiaf e enviaConfirmacaoSincronizacaoTabelaUsuario
	 * para sincronizar as tabelas de Usuários do SIAF e SMC
	 * 
	 */
	//Método para sincronizar as tabelas Usuário do Banco de Dados do SIAF com a da aplicação SMC
	public static boolean getDadosTabelaUsuarioSiaf(Context context){
		HttpClient httpClient = new DefaultHttpClient();
		HttpGet httpGet = new HttpGet(RestClientUsuario.ENDERECO_WEBSERVICE_SINCRONIZA_USUARIO);
		HttpResponse response;
		try{ 
			response = httpClient.execute(httpGet);
			Log.i("smc","Usuário Response Status:[" + response.getStatusLine().toString() + "]");
			HttpEntity entity = response.getEntity();
			
			if(entity != null){
				InputStream inStream = entity.getContent();
				String result = RestClientUsuario.convertStreamToString(inStream);
				Log.i("smc","Objeto JSON que chegou do Web Service Sincroniza Dados Usuario" + result);
				inStream.close();
				
				//Parser criado manualmente para sincronização de apenas um registro retornado do SIAF (o objeto JSON não consegue converter para array sem esse parser)
				if(result.startsWith("{\"usuarioJson\":{\"")){
					//Log.i("smc","Substring:" + result.substring(15, result.length() - 1));
					result = "{\"usuarioJson\":[" + result.substring(15, result.length() - 2) + "}]}";
					//Log.i("smc","Result da Substring:" + result);
				}
				
				//Caso as tabelas já estejam atualizadas. Retornou uma lista vazia (null). Nenhum objeto com sincronizado=false no SIAF
				if(!result.equals("null")){
					try{
						JSONObject json = new JSONObject(result);
						JSONArray nameArray = json.names();
						JSONArray valArray = json.toJSONArray(nameArray);
						for (int i = 0; i < valArray.length(); i++) {
							if(i == 0){
								listaUsuario = new ArrayList<Usuario>();
								JSONArray valUsuario = json.getJSONArray("usuarioJson");
								for (int j = 0; j < valUsuario.length(); j++) {
									Usuario u = new Usuario();
									u.setCodigoUsuario(valUsuario.getJSONObject(j).getInt("codigousuario"));
									u.setNome(valUsuario.getJSONObject(j).getString("nome").toString());
									u.setUsuario(valUsuario.getJSONObject(j).getString("usuario").toString());
									u.setSenha(valUsuario.getJSONObject(j).getString("senha").toString());
									u.setTipoUsuario(valUsuario.getJSONObject(j).getInt("tipousuario"));
									Log.i("json", "Código.: " + valUsuario.getJSONObject(j).getInt("codigousuario") + " | Nome...: " + valUsuario.getJSONObject(j).getString("nome").toString() + " | Usuario: " + valUsuario.getJSONObject(j).getString("usuario").toString() + " | Senha..: " + valUsuario.getJSONObject(j).getString("senha").toString() + " | Tipo Us: " + valUsuario.getJSONObject(j).getString("tipousuario").toString() + '\n' + '\n');
									//Verifica se o usuário realmente foi inserido no Banco de Dados do dispositivo.
									//Caso ele já exista, o registro será atualizado e caso contrario, inserido.
									Usuario uEncontrado = new Usuario();
									uEncontrado = (Usuario) new UsuarioDAO(context).buscarUsuarioPeloCodigo(u.getCodigoUsuario());
									Log.i("smc","RestClient:getDadosTabelasSiaf | Usuário.getCodigoUsuario(): " + uEncontrado.getCodigoUsuario());
									if(!(uEncontrado.getCodigoUsuario() == null)){
										Log.i("smc","RestClient:getDadosTabelasSiaf | Encontrou o usuário " + uEncontrado.getNome());
										if(new UsuarioDAO(context).atualizaUsuario(u)){
											listaUsuario.add(u);
										}
										
									}
									else{
										if(new UsuarioDAO(context).inserirUsuario(u)){
											listaUsuario.add(u);
										}
									}	
								}	
							}
							//Colocar aqui os outros ifs das outras tabelas
						}
						//Confirma os usuários recebidos para setar o sincronizado da tabela do SIAF para true
						new Thread(){
							public void run(){
								Looper.prepare();
								//Método que retorna os usuários recebidos na sincronização
								if(!listaUsuario.isEmpty()){
									enviaConfirmacaoSincronizacaoTabelaUsuario(listaUsuario);
								}
								Looper.loop();
							}
						}.start();
						return true;
					}catch(JSONException e){
						Log.e("erro", "RestClient:getDadosTabelasSiaf() | There was an error parsing the JSON",e);
						return false;
					}
				}
				else{
					//Não tem nada para sincronizar. As tabelas já estão atualizadas
					return true;
				}
			}
		}catch(ClientProtocolException e){
			Log.e("erro", "RestClient:getDadosTabelasSiaf() | There was a protocol based error",e);
			return false;
		}catch(IOException e){
			Log.e("erro", "RestClient:getDadosTabelasSiaf() | There was an IO Stream related error",e);
			return false;
		}	
		return false;
	}
	
	//Método que envia a confirmação de quais usuários foram recebidos na sincronização e realmente persistido no Banco de Dados do SMC
	public static boolean enviaConfirmacaoSincronizacaoTabelaUsuario(List<Usuario> listaUsuarios){
		HttpClient httpClient = new DefaultHttpClient();
		HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), 10000);
		HttpResponse response;
		JSONObject json;
		List<JSONObject> lJson = new ArrayList<JSONObject>();
		try{
			HttpPut put = new HttpPut(ENDERECO_WEBSERVICE_SINCRONIZA_USUARIO);
			for (Usuario usuario : listaUsuarios) {
				json = new JSONObject();
				json.put("codigousuario", usuario.getCodigoUsuario());
				lJson.add(json);
			}
			StringEntity se = new StringEntity("{\"usuarioJson\":" + lJson.toString() + "}");
			Log.i("smc","RestClient:enviaConfirmacaoSincronizacao | Objeto lJson " + lJson);
			put.setEntity(se);
			put.setHeader("Accept","application/json");
			put.setHeader("Content-type", "application/json");
			response = httpClient.execute(put);
			if(response != null){
				InputStream in = response.getEntity().getContent();
				Log.i("smc","RestClient:enviaConfirmacaoSincronizacao | Finalizando a Sincronização");
				Log.i("smc", "Conteúdo de inputstream: " + in.toString());
				return true;
			}
		}catch(Exception e){
			e.printStackTrace();
			Log.e("erro","Cannot Estabilish Connection");
			return false;
		}
		return false;
	}
}